Laboratório R 02¶
Aluno Wesley Rodrigues
Curso Mestrado em Computação Aplicada
Turma T06
Disciplina Big Data & Analitycs
Atividade Laboratório R 02
Data 10/OUT/2023
As atividades propostas em sala tem como objetivo familiarizar o aluno com as operações comuns em análise de conjuntos de dados. Esta atividade foi realizada em Python, que foi colocado como alternativa ao R.

# Nesta seção as bibliotecas necessárias para o funcionamento do código são importadas
import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestRegressor
Resolução dos Exercícios¶
1. Considere os conjuntos de dados house price cenário 1 e cenário 2, disponível no arquivo Data_HousePrice_Area.xlsx.¶
a. Faça uma análise descritiva para ambos os conjuntos. O que se pode notar de diferente?
b. Ajuste um modelo de regressão linear simples para ambos conjuntos no qual o valor seja explicado pela a área. Discuta.
c. Se uma casa possuir 1300 ft², qual seria o preço esperado de acordo com o modelo do cenário 1? E de acordo com o modelo do cenário 2?
hp_cen1 = pd.read_excel('./datasets/Data_HousePrice_Area.xlsx', sheet_name='Cenario 1')
hp_cen1
| Square Feet | House Price | |
|---|---|---|
| 0 | 1400 | 245 |
| 1 | 1600 | 312 |
| 2 | 1700 | 279 |
| 3 | 1875 | 308 |
| 4 | 1100 | 199 |
| 5 | 1550 | 219 |
| 6 | 2350 | 405 |
| 7 | 2450 | 324 |
| 8 | 1425 | 319 |
| 9 | 1700 | 255 |
hp_cen2 = pd.read_excel('./datasets/Data_HousePrice_Area.xlsx', sheet_name='Cenario 2')
hp_cen2
| Square Feet | House Price | |
|---|---|---|
| 0 | 1400 | 245 |
| 1 | 1800 | 312 |
| 2 | 1700 | 279 |
| 3 | 1875 | 308 |
| 4 | 1200 | 199 |
| 5 | 1480 | 219 |
| 6 | 2350 | 405 |
| 7 | 2100 | 324 |
| 8 | 2000 | 319 |
| 9 | 1700 | 255 |
hp_cen1.describe()
| Square Feet | House Price | |
|---|---|---|
| count | 10.000000 | 10.000000 |
| mean | 1715.000000 | 286.500000 |
| std | 417.864944 | 60.185362 |
| min | 1100.000000 | 199.000000 |
| 25% | 1456.250000 | 247.500000 |
| 50% | 1650.000000 | 293.500000 |
| 75% | 1831.250000 | 317.250000 |
| max | 2450.000000 | 405.000000 |
hp_cen2.describe()
| Square Feet | House Price | |
|---|---|---|
| count | 10.000000 | 10.000000 |
| mean | 1760.500000 | 286.500000 |
| std | 343.983607 | 60.185362 |
| min | 1200.000000 | 199.000000 |
| 25% | 1535.000000 | 247.500000 |
| 50% | 1750.000000 | 293.500000 |
| 75% | 1968.750000 | 317.250000 |
| max | 2350.000000 | 405.000000 |
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=hp_cen1['Square Feet'], mode='lines+markers', name='Cenario 1'))
fig.add_trace(go.Scatter(y=hp_cen2['Square Feet'], mode='lines+markers', name='Cenario 2'))
fig.show()
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=hp_cen1['House Price'], mode='lines+markers', name='Cenario 1'))
fig.add_trace(go.Scatter(y=hp_cen2['House Price'], mode='lines+markers', name='Cenario 2'))
fig.show()
a) Os dois cenários tem valores idênticos para os preços das casas, mas a coluna pés quadrados tem variações.
lr1 = LinearRegression()
X1 = hp_cen1['Square Feet'].values.reshape(-1,1)
y1 = hp_cen1['House Price'].values
lr1.fit(X1, y1)
print(f'Parametros da regressão: intercept: {lr1.intercept_}, coef: {lr1.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=y1, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lr1.predict(X1), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: 98.24832962138078, coef: [0.10976774], formula: (intercept + coef * variável = resultado)
lr2 = LinearRegression()
X2 = hp_cen2['Square Feet'].values.reshape(-1,1)
y2 = hp_cen2['House Price'].values
lr2.fit(X2, y2)
print(f'Parametros da regressão: intercept: {lr2.intercept_}, coef: {lr2.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=y2, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lr2.predict(X2), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: -9.645089196631716, coef: [0.16821647], formula: (intercept + coef * variável = resultado)
# c. Se uma casa possuir 1300 ft², qual seria o preço esperado de acordo com o modelo do cenário 1? E de acordo com o modelo do cenário 2?
print('Casa de 1300 ft2 de acordo com o modelo do cenário 1:', lr1.predict([[3200]]))
Casa de 1300 ft2 de acordo com o modelo do cenário 1: [449.50509068]
print('Casa de 1300 ft2 de acordo com o modelo do cenário 2:', lr2.predict([[3200]]))
Casa de 1300 ft2 de acordo com o modelo do cenário 2: [528.64760346]
2. Considere os conjuntos de dados de energia, disponível no arquivo Data_ConsumoEnergia.xlsx.¶
a. Faça uma análise descritiva.
b. Qual seria a variável resposta e a explicativa? Qual modelo de regressão você ajustaria?
c. Ajuste modelos de regressão linear simples e polinomiais de grau 2, 3 e 4. Qual deles é melhor? Qual o problema de se ajustar um modelo polinomial de grau bem alto?
df_energia = pd.read_excel('./datasets/Data_ConsumoEnergia.xlsx', sheet_name='Planilha1')
df_energia
| Ajuste na maquina | Consumo de energia | |
|---|---|---|
| 0 | 11.15 | 21.6 |
| 1 | 15.70 | 4.0 |
| 2 | 18.90 | 1.8 |
| 3 | 19.40 | 1.0 |
| 4 | 21.40 | 1.0 |
| 5 | 21.70 | 0.8 |
| 6 | 25.30 | 3.8 |
| 7 | 26.40 | 7.4 |
| 8 | 26.70 | 4.3 |
| 9 | 29.10 | 36.2 |
df_energia.describe()
| Ajuste na maquina | Consumo de energia | |
|---|---|---|
| count | 10.000000 | 10.000000 |
| mean | 21.575000 | 8.190000 |
| std | 5.529479 | 11.622818 |
| min | 11.150000 | 0.800000 |
| 25% | 19.025000 | 1.200000 |
| 50% | 21.550000 | 3.900000 |
| 75% | 26.125000 | 6.625000 |
| max | 29.100000 | 36.200000 |
px.box(df_energia, height=600)
df_energia.corr()
| Ajuste na maquina | Consumo de energia | |
|---|---|---|
| Ajuste na maquina | 1.000000 | 0.153104 |
| Consumo de energia | 0.153104 | 1.000000 |
fig = px.line(df_energia, height=600)
fig.show()
A variável alvo é o consumo de energia. Fazendo ajustes na máquina queremos verificar o impacto no consumo de energia. As duas variáveis tem baixa correlação. Um modelo de regressão poderia ser utilizado, gerando uma curva que se pareça com uma parábola.
lr = LinearRegression()
X = df_energia['Ajuste na maquina'].values.reshape(-1,1)
y = df_energia['Consumo de energia'].values
polin = PolynomialFeatures(degree=2)
X_polin = polin.fit_transform(X)
lr.fit(X_polin, y)
fig = px.line(height=600, title='Polinomio de Grau 2')
fig.add_trace(go.Scatter(y=y, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lr.predict(X_polin), mode='lines+markers', name='Regressão Polinomial'))
fig.show()
polin = PolynomialFeatures(degree=3)
X_polin = polin.fit_transform(X)
lr.fit(X_polin, y)
fig = px.line(height=600, title='Polinomio de Grau 3')
fig.add_trace(go.Scatter(y=y, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lr.predict(X_polin), mode='lines+markers', name='Regressão Polinomial'))
fig.show()
polin = PolynomialFeatures(degree=4)
X_polin = polin.fit_transform(X)
lr.fit(X_polin, y)
fig = px.line(height=600, title='Polinomio de Grau 4')
fig.add_trace(go.Scatter(y=y, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lr.predict(X_polin), mode='lines+markers', name='Regressão Polinomial'))
fig.show()
Os modelos com graus mais altos ficaram bastante precisos, mas teriam dificuldade em generalizar para novos dados. Eles decoram os dados de treino, em um fenômeno conhecido como overfitting.
3. Considere o conjunto de dados SALES_X_YOUTUBE (arquivo DadosLab02.xlsx).¶
a. Faça uma análise descritiva.
b. Considere sales como variável resposta e youtube como explicativa. Qual modelo de regressão você ajustaria?
c. Ajuste um modelo de regressão linear múltipla tendo a variável sales como resposta e as demais variáveis como explicativas. Interprete os parâmetros dos modelos. De acordo com o modelo, qual das variáveis tem maior efeito nas vendas?
sales_youtube = pd.read_excel('./datasets/DadosLab02.xlsx', sheet_name='SALES_X_YOUTUBE', usecols='B:E')
sales_youtube.index += 1
sales_youtube
| youtube | newspaper | sales | ||
|---|---|---|---|---|
| 1 | 276.12 | 45.36 | 83.04 | 26.52 |
| 2 | 53.40 | 47.16 | 54.12 | 12.48 |
| 3 | 20.64 | 55.08 | 83.16 | 11.16 |
| 4 | 181.80 | 49.56 | 70.20 | 22.20 |
| 5 | 216.96 | 12.96 | 70.08 | 15.48 |
| ... | ... | ... | ... | ... |
| 196 | 45.84 | 4.44 | 16.56 | 9.12 |
| 197 | 113.04 | 5.88 | 9.72 | 11.64 |
| 198 | 212.40 | 11.16 | 7.68 | 15.36 |
| 199 | 340.32 | 50.40 | 79.44 | 30.60 |
| 200 | 278.52 | 10.32 | 10.44 | 16.08 |
200 rows × 4 columns
# a. Faça uma análise descritiva.
sales_youtube.describe()
| youtube | newspaper | sales | ||
|---|---|---|---|---|
| count | 200.000000 | 200.000000 | 200.000000 | 200.000000 |
| mean | 176.451000 | 27.916800 | 36.664800 | 16.827000 |
| std | 103.025084 | 17.816171 | 26.134345 | 6.260948 |
| min | 0.840000 | 0.000000 | 0.360000 | 1.920000 |
| 25% | 89.250000 | 11.970000 | 15.300000 | 12.450000 |
| 50% | 179.700000 | 27.480000 | 30.900000 | 15.480000 |
| 75% | 262.590000 | 43.830000 | 54.120000 | 20.880000 |
| max | 355.680000 | 59.520000 | 136.800000 | 32.400000 |
fig = pd.plotting.scatter_matrix(sales_youtube, figsize=(18,9))
plt.show()
px.box(sales_youtube, height=600)
# b. Considere sales como variável resposta e youtube como explicativa. Qual modelo de regressão você ajustaria?
lr = LinearRegression()
sales_youtube_ordenado = sales_youtube.sort_values(by='sales')
X = sales_youtube_ordenado['youtube'].values.reshape(-1,1)
y = sales_youtube_ordenado['sales'].values
lr.fit(X, y)
print(f'Parametros da regressão: intercept: {lr.intercept_}, coef: {lr.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=y, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lr.predict(X), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: 8.439112258953228, coef: [0.04753664], formula: (intercept + coef * variável = resultado)
# c. Ajuste um modelo de regressão linear múltipla tendo a variável sales como resposta e as demais variáveis como explicativas. Interprete os parâmetros dos modelos. De acordo com o modelo, qual das variáveis tem maior efeito nas vendas?
lrm = LinearRegression()
Xm = sales_youtube_ordenado.drop('sales', axis=1).values
ym = sales_youtube_ordenado['sales'].values
lrm.fit(Xm, ym)
print(f'Parametros da regressão: intercept: {lrm.intercept_}, coef: {lrm.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=ym, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lrm.predict(Xm), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: 3.5266672433512927, coef: [ 0.04576465 0.18853002 -0.00103749], formula: (intercept + coef * variável = resultado)
4. Considere o conjunto de dados CREDIT SCORE X RENDA E OUTRAS V (dados DadosLab02.xlsx).¶
a. Faça uma análise descritiva univariada e depois uma bivariada tendo a ST como variável resposta.
b. Qual modelo de regressão você ajustaria? Discuta sobre os possíveis objetivos e modelagens para o problema.
c. Ajuste um modelo de regressão logística tendo ST como variável resposta e as demais variáveis como explicativas. Tente interpretar os parâmetros.
d. Classifique as observações de acordo com o modelo. Qual foi a taxa de acerto?
credito = pd.read_excel('./datasets/DadosLab02.xlsx', sheet_name='CREDIT SCORE X RENDA E OUTRAS V', usecols='S:V', names=['st', 'renda', 'dependentes', 'vinculo_emprego'])
credito.index += 1
credito
| st | renda | dependentes | vinculo_emprego | |
|---|---|---|---|---|
| 1 | 0 | 2.5 | 3 | 1 |
| 2 | 1 | 1.7 | 3 | 1 |
| 3 | 0 | 4.0 | 2 | 1 |
| 4 | 1 | 2.3 | 2 | 1 |
| 5 | 1 | 3.7 | 4 | 0 |
| ... | ... | ... | ... | ... |
| 88 | 1 | 1.3 | 2 | 1 |
| 89 | 1 | 2.4 | 2 | 1 |
| 90 | 0 | 4.3 | 2 | 0 |
| 91 | 1 | 1.8 | 0 | 1 |
| 92 | 0 | 2.4 | 2 | 0 |
92 rows × 4 columns
# a. Faça uma análise descritiva univariada e depois uma bivariada tendo a ST como variável resposta.
credito.describe()
| st | renda | dependentes | vinculo_emprego | |
|---|---|---|---|---|
| count | 92.000000 | 92.000000 | 92.000000 | 92.000000 |
| mean | 0.445652 | 3.126087 | 2.141304 | 0.543478 |
| std | 0.499761 | 1.347025 | 1.075006 | 0.500835 |
| min | 0.000000 | 1.200000 | 0.000000 | 0.000000 |
| 25% | 0.000000 | 2.175000 | 1.000000 | 0.000000 |
| 50% | 0.000000 | 2.900000 | 2.000000 | 1.000000 |
| 75% | 1.000000 | 4.000000 | 3.000000 | 1.000000 |
| max | 1.000000 | 8.200000 | 5.000000 | 1.000000 |
px.box(credito, height=600)
fig = pd.plotting.scatter_matrix(credito[['st', 'renda']], figsize=(18,9))
plt.show()
fig = pd.plotting.scatter_matrix(credito[['st', 'dependentes']], figsize=(18,9))
plt.show()
fig = pd.plotting.scatter_matrix(credito[['st', 'vinculo_emprego']], figsize=(18,9))
plt.show()
px.imshow(credito.corr(), height=600)
# b. Qual modelo de regressão você ajustaria? Discuta sobre os possíveis objetivos e modelagens para o problema.
lrm = LinearRegression()
credito_ordenado = credito.sort_values(by='st')
Xm = credito_ordenado.drop('st', axis=1).values
ym = credito_ordenado['st'].values
lrm.fit(Xm, ym)
print(f'Parametros da regressão: intercept: {lrm.intercept_}, coef: {lrm.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=ym, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lrm.predict(Xm), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: 0.5414282060295561, coef: [-0.1701675 0.10872886 0.37418388], formula: (intercept + coef * variável = resultado)
Após executar a regressão linear como nos exemplos anteriores e observar o gráfico, fica evidente que este não é um problema de regressão, mas de classificação, no qual um indivíduo, baseado em sua renda, dependentes e vínculo empregatício, deve ter o crédito negado ou aprovado. Por isso, o modelo precisa ser alterado para uma regressão logística, que vai responder melhor de acordo com a classe de saída.
# c. Ajuste um modelo de regressão logística tendo ST como variável resposta e as demais variáveis como explicativas. Tente interpretar os parâmetros.
lgrm = LogisticRegression()
credito_ordenado = credito.sort_values(by='st')
Xm = credito_ordenado.drop('st', axis=1).values
ym = credito_ordenado['st'].values
lgrm.fit(Xm, ym)
print(f'Parametros da regressão: intercept: {lrm.intercept_}, coef: {lrm.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=ym, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lgrm.predict(Xm), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: 0.5414282060295561, coef: [-0.1701675 0.10872886 0.37418388], formula: (intercept + coef * variável = resultado)
# d. Classifique as observações de acordo com o modelo. Qual foi a taxa de acerto?
from sklearn.metrics import roc_auc_score
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
y_score = lgrm.predict_proba(Xm)[:, 1]
roc_auc_score(ym, y_score)
0.9478718316594931
cm = confusion_matrix(ym, lgrm.predict(Xm), labels=lgrm.classes_)
fig, ax = plt.subplots(figsize=(12,12))
ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=lgrm.classes_).plot(ax=ax)
plt.show()
5. Considere o conjunto de dados disponível em aqui (dados crus aqui).¶
a. Observando o conjunto de dados (nome das colunas e tipos de dados), infira qual é o objetivo, identificando as possíveis variáveis respostas e as variáveis explicativas.
b. Faça uma análise descritiva de acordo com o que foi discutido no item anterior;
c. Ajuste um modelo (regressão ou ANOVA) que seja adequado ao problema. Discuta os pressupostos da modelagem.
d. Verifique se o modelo proposto é adequado fazendo uma análise de resíduos.
diet = pd.read_csv('./datasets/diet.csv')
diet = diet.set_index('id')
diet.sample(10)
| gender | age | height | diet.type | initial.weight | final.weight | |
|---|---|---|---|---|---|---|
| id | ||||||
| 22 | Male | 42 | 166 | A | 85 | 81.5 |
| 21 | Male | 52 | 177 | A | 83 | 79.1 |
| 70 | Male | 37 | 173 | C | 78 | 77.5 |
| 30 | Female | 43 | 171 | B | 61 | 56.7 |
| 44 | Male | 33 | 190 | B | 76 | 72.5 |
| 69 | Male | 29 | 166 | C | 76 | 72.5 |
| 42 | Male | 38 | 199 | B | 75 | 72.6 |
| 1 | Female | 22 | 159 | A | 58 | 54.2 |
| 34 | Female | 54 | 173 | B | 63 | 59.4 |
| 14 | Female | 37 | 167 | A | 82 | 81.1 |
# a. Observando o conjunto de dados (nome das colunas e tipos de dados), infira qual é o objetivo, identificando as possíveis variáveis respostas e as variáveis explicativas.
olhando para os dados, concluí que trata-se de uma base de pessoas que fizeram dietas para perder peso. Para tornar a visualização mais eficiente, adicionei uma nova coluna com a diferença entre o peso atual e o peso inicial, onde maiores diferenças (com perda de peso) são melhores.
diet['resultado'] = diet['initial.weight'] - diet['final.weight']
diet.sample(10)
| gender | age | height | diet.type | initial.weight | final.weight | resultado | |
|---|---|---|---|---|---|---|---|
| id | |||||||
| 22 | Male | 42 | 166 | A | 85 | 81.5 | 3.5 |
| 69 | Male | 29 | 166 | C | 76 | 72.5 | 3.5 |
| 37 | Female | 16 | 165 | B | 68 | 63.8 | 4.2 |
| 63 | Female | 35 | 171 | C | 72 | 64.4 | 7.6 |
| 20 | Male | 25 | 165 | A | 80 | 77.6 | 2.4 |
| 19 | Male | 43 | 162 | A | 80 | 71.0 | 9.0 |
| 62 | Female | 31 | 170 | C | 72 | 71.1 | 0.9 |
| 5 | Female | 50 | 170 | A | 65 | 62.2 | 2.8 |
| 47 | Male | 44 | 163 | B | 79 | 73.6 | 5.4 |
| 59 | Female | 45 | 155 | C | 69 | 61.8 | 7.2 |
Uma pessoa que pesa 100 quilos e perde 10 quilos perdeu mais de forma absoluta e menos de forma relativa que uma pessoa que pesa 50 quilos e perde 9 quilos. Desta forma, criei uma coluna que mostra o quanto a proporção perdida representa do total.
diet['perda_relativa'] = diet['resultado'] / diet['initial.weight']
diet.sample(10)
| gender | age | height | diet.type | initial.weight | final.weight | resultado | perda_relativa | |
|---|---|---|---|---|---|---|---|---|
| id | ||||||||
| 62 | Female | 31 | 170 | C | 72 | 71.1 | 0.9 | 0.012500 |
| 11 | Female | 60 | 173 | A | 72 | 70.5 | 1.5 | 0.020833 |
| 77 | Male | 40 | 167 | C | 87 | 77.8 | 9.2 | 0.105747 |
| 10 | Female | 45 | 165 | A | 70 | 66.9 | 3.1 | 0.044286 |
| 27 | Female | 44 | 174 | B | 58 | 60.1 | -2.1 | -0.036207 |
| 12 | Female | 48 | 156 | A | 72 | 69.0 | 3.0 | 0.041667 |
| 31 | Female | 20 | 169 | B | 62 | 55.0 | 7.0 | 0.112903 |
| 76 | Male | 28 | 164 | C | 85 | 79.7 | 5.3 | 0.062353 |
| 28 | Female | 37 | 172 | B | 58 | 56.0 | 2.0 | 0.034483 |
| 34 | Female | 54 | 173 | B | 63 | 59.4 | 3.6 | 0.057143 |
# b. Faça uma análise descritiva de acordo com o que foi discutido no item anterior;
fig = pd.plotting.scatter_matrix(diet, figsize=(18,9))
plt.show()
diet.describe(include='all')
| gender | age | height | diet.type | initial.weight | final.weight | resultado | perda_relativa | |
|---|---|---|---|---|---|---|---|---|
| count | 76 | 76.000000 | 76.000000 | 76 | 76.000000 | 76.000000 | 76.000000 | 76.000000 |
| unique | 2 | NaN | NaN | 3 | NaN | NaN | NaN | NaN |
| top | Female | NaN | NaN | C | NaN | NaN | NaN | NaN |
| freq | 43 | NaN | NaN | 27 | NaN | NaN | NaN | NaN |
| mean | NaN | 39.223684 | 170.776316 | NaN | 72.289474 | 68.343421 | 3.946053 | 0.054782 |
| std | NaN | 9.908379 | 11.419981 | NaN | 7.974653 | 8.058938 | 2.505803 | 0.035185 |
| min | NaN | 16.000000 | 141.000000 | NaN | 58.000000 | 53.000000 | -2.100000 | -0.036207 |
| 25% | NaN | 32.500000 | 163.750000 | NaN | 66.000000 | 61.950000 | 2.300000 | 0.031576 |
| 50% | NaN | 39.000000 | 169.000000 | NaN | 72.000000 | 68.950000 | 3.700000 | 0.051282 |
| 75% | NaN | 47.250000 | 175.250000 | NaN | 78.000000 | 73.675000 | 5.650000 | 0.077245 |
| max | NaN | 60.000000 | 201.000000 | NaN | 88.000000 | 84.500000 | 9.200000 | 0.123188 |
diet_numericos = pd.get_dummies(diet, dtype='int64')
diet_numericos.sample(10)
| age | height | initial.weight | final.weight | resultado | perda_relativa | gender_Female | gender_Male | diet.type_A | diet.type_B | diet.type_C | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||
| 39 | 30 | 161 | 76 | 72.7 | 3.3 | 0.043421 | 1 | 0 | 0 | 1 | 0 |
| 75 | 49 | 177 | 84 | 79.9 | 4.1 | 0.048810 | 0 | 1 | 0 | 0 | 1 |
| 51 | 31 | 182 | 80 | 75.7 | 4.3 | 0.053750 | 0 | 1 | 0 | 1 | 0 |
| 54 | 21 | 159 | 64 | 60.6 | 3.4 | 0.053125 | 1 | 0 | 0 | 0 | 1 |
| 37 | 16 | 165 | 68 | 63.8 | 4.2 | 0.061765 | 1 | 0 | 0 | 1 | 0 |
| 28 | 37 | 172 | 58 | 56.0 | 2.0 | 0.034483 | 1 | 0 | 0 | 1 | 0 |
| 20 | 25 | 165 | 80 | 77.6 | 2.4 | 0.030000 | 0 | 1 | 1 | 0 | 0 |
| 5 | 50 | 170 | 65 | 62.2 | 2.8 | 0.043077 | 1 | 0 | 1 | 0 | 0 |
| 1 | 22 | 159 | 58 | 54.2 | 3.8 | 0.065517 | 1 | 0 | 1 | 0 | 0 |
| 43 | 54 | 196 | 75 | 69.2 | 5.8 | 0.077333 | 0 | 1 | 0 | 1 | 0 |
diet_numericos.describe(include='all')
| age | height | initial.weight | final.weight | resultado | perda_relativa | gender_Female | gender_Male | diet.type_A | diet.type_B | diet.type_C | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 | 76.000000 |
| mean | 39.223684 | 170.776316 | 72.289474 | 68.343421 | 3.946053 | 0.054782 | 0.565789 | 0.434211 | 0.315789 | 0.328947 | 0.355263 |
| std | 9.908379 | 11.419981 | 7.974653 | 8.058938 | 2.505803 | 0.035185 | 0.498946 | 0.498946 | 0.467918 | 0.472953 | 0.481773 |
| min | 16.000000 | 141.000000 | 58.000000 | 53.000000 | -2.100000 | -0.036207 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
| 25% | 32.500000 | 163.750000 | 66.000000 | 61.950000 | 2.300000 | 0.031576 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
| 50% | 39.000000 | 169.000000 | 72.000000 | 68.950000 | 3.700000 | 0.051282 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
| 75% | 47.250000 | 175.250000 | 78.000000 | 73.675000 | 5.650000 | 0.077245 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 |
| max | 60.000000 | 201.000000 | 88.000000 | 84.500000 | 9.200000 | 0.123188 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 |
diet_numericos.corr()
| age | height | initial.weight | final.weight | resultado | perda_relativa | gender_Female | gender_Male | diet.type_A | diet.type_B | diet.type_C | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| age | 1.000000 | 0.083403 | 0.033931 | 0.055764 | -0.071361 | -0.098551 | -0.012456 | 0.012456 | 0.113974 | -0.001685 | -0.109043 |
| height | 0.083403 | 1.000000 | 0.157229 | 0.190821 | -0.113324 | -0.137825 | -0.344876 | 0.344876 | -0.029023 | 0.263136 | -0.230130 |
| initial.weight | 0.033931 | 0.157229 | 1.000000 | 0.951204 | 0.123297 | -0.051034 | -0.745419 | 0.745419 | 0.050213 | -0.177595 | 0.125575 |
| final.weight | 0.055764 | 0.190821 | 0.951204 | 1.000000 | -0.188928 | -0.354770 | -0.730062 | 0.730062 | 0.104512 | -0.116439 | 0.012801 |
| resultado | -0.071361 | -0.113324 | 0.123297 | -0.188928 | 1.000000 | 0.978563 | -0.024318 | 0.024318 | -0.176320 | -0.190712 | 0.358469 |
| perda_relativa | -0.098551 | -0.137825 | -0.051034 | -0.354770 | 0.978563 | 1.000000 | 0.113447 | -0.113447 | -0.180135 | -0.175616 | 0.347355 |
| gender_Female | -0.012456 | -0.344876 | -0.745419 | -0.730062 | -0.024318 | 0.113447 | 1.000000 | -1.000000 | 0.024046 | -0.008178 | -0.015327 |
| gender_Male | 0.012456 | 0.344876 | 0.745419 | 0.730062 | 0.024318 | -0.113447 | -1.000000 | 1.000000 | -0.024046 | 0.008178 | 0.015327 |
| diet.type_A | 0.113974 | -0.029023 | 0.050213 | 0.104512 | -0.176320 | -0.180135 | 0.024046 | -0.024046 | 1.000000 | -0.475651 | -0.504299 |
| diet.type_B | -0.001685 | 0.263136 | -0.177595 | -0.116439 | -0.190712 | -0.175616 | -0.008178 | 0.008178 | -0.475651 | 1.000000 | -0.519719 |
| diet.type_C | -0.109043 | -0.230130 | 0.125575 | 0.012801 | 0.358469 | 0.347355 | -0.015327 | 0.015327 | -0.504299 | -0.519719 | 1.000000 |
px.imshow(diet_numericos.corr(), height=600)
px.box(diet_numericos, height=600)
O boxplot mopstra que o campo height tem outliers abaixo e acima dos valores esperados.
Vamos conhecer as 10 pessoas que perderam mais peso, de forma relativa e absoluta.
top_rel = diet_numericos.sort_values(by='perda_relativa', ascending=False)[:10]
top_rel
| age | height | initial.weight | final.weight | resultado | perda_relativa | gender_Female | gender_Male | diet.type_A | diet.type_B | diet.type_C | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||
| 8 | 28 | 176 | 69 | 60.5 | 8.5 | 0.123188 | 1 | 0 | 1 | 0 | 0 |
| 56 | 36 | 160 | 66 | 58.2 | 7.8 | 0.118182 | 1 | 0 | 0 | 0 | 1 |
| 52 | 51 | 165 | 60 | 53.0 | 7.0 | 0.116667 | 1 | 0 | 0 | 0 | 1 |
| 31 | 20 | 169 | 62 | 55.0 | 7.0 | 0.112903 | 1 | 0 | 0 | 1 | 0 |
| 19 | 43 | 162 | 80 | 71.0 | 9.0 | 0.112500 | 0 | 1 | 1 | 0 | 0 |
| 72 | 26 | 179 | 78 | 69.4 | 8.6 | 0.110256 | 0 | 1 | 0 | 0 | 1 |
| 77 | 40 | 167 | 87 | 77.8 | 9.2 | 0.105747 | 0 | 1 | 0 | 0 | 1 |
| 63 | 35 | 171 | 72 | 64.4 | 7.6 | 0.105556 | 1 | 0 | 0 | 0 | 1 |
| 55 | 22 | 169 | 65 | 58.2 | 6.8 | 0.104615 | 1 | 0 | 0 | 0 | 1 |
| 59 | 45 | 155 | 69 | 61.8 | 7.2 | 0.104348 | 1 | 0 | 0 | 0 | 1 |
top_abs = diet_numericos.sort_values(by='resultado', ascending=False)[:10]
top_abs
| age | height | initial.weight | final.weight | resultado | perda_relativa | gender_Female | gender_Male | diet.type_A | diet.type_B | diet.type_C | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| id | |||||||||||
| 77 | 40 | 167 | 87 | 77.8 | 9.2 | 0.105747 | 0 | 1 | 0 | 0 | 1 |
| 19 | 43 | 162 | 80 | 71.0 | 9.0 | 0.112500 | 0 | 1 | 1 | 0 | 0 |
| 72 | 26 | 179 | 78 | 69.4 | 8.6 | 0.110256 | 0 | 1 | 0 | 0 | 1 |
| 8 | 28 | 176 | 69 | 60.5 | 8.5 | 0.123188 | 1 | 0 | 1 | 0 | 0 |
| 49 | 37 | 198 | 79 | 71.1 | 7.9 | 0.100000 | 0 | 1 | 0 | 1 | 0 |
| 56 | 36 | 160 | 66 | 58.2 | 7.8 | 0.118182 | 1 | 0 | 0 | 0 | 1 |
| 63 | 35 | 171 | 72 | 64.4 | 7.6 | 0.105556 | 1 | 0 | 0 | 0 | 1 |
| 61 | 37 | 170 | 70 | 62.7 | 7.3 | 0.104286 | 1 | 0 | 0 | 0 | 1 |
| 59 | 45 | 155 | 69 | 61.8 | 7.2 | 0.104348 | 1 | 0 | 0 | 0 | 1 |
| 31 | 20 | 169 | 62 | 55.0 | 7.0 | 0.112903 | 1 | 0 | 0 | 1 | 0 |
# c. Ajuste um modelo (regressão ou ANOVA) que seja adequado ao problema. Discuta os pressupostos da modelagem.
lrm = LinearRegression()
diet_numericos_ord = diet_numericos.sort_values(by='perda_relativa')
campos_relevantes = ['age', 'height', 'initial.weight', 'gender_Female', 'gender_Male', 'diet.type_A', 'diet.type_B', 'diet.type_C']
Xm = diet_numericos_ord[campos_relevantes].values
ym = diet_numericos_ord['perda_relativa'].values
lrm.fit(Xm, ym)
print(f'Parametros da regressão: intercept: {lrm.intercept_}, coef: {lrm.coef_}, formula: (intercept + coef * variável = resultado)')
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=ym, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=lrm.predict(Xm), mode='lines+markers', name='Regressão'))
fig.show()
Parametros da regressão: intercept: 0.07492514872979122, coef: [-2.05772192e-04 -5.62419199e-05 -4.83447796e-05 3.65185030e-03 -3.65185030e-03 -8.50759794e-03 -8.03967849e-03 1.65472764e-02], formula: (intercept + coef * variável = resultado)
rfr = RandomForestRegressor()
diet_numericos_ord = diet_numericos.sort_values(by='perda_relativa')
campos_relevantes = ['age', 'height', 'initial.weight', 'gender_Female', 'gender_Male', 'diet.type_A', 'diet.type_B', 'diet.type_C']
Xm = diet_numericos_ord[campos_relevantes]
ym = diet_numericos_ord['perda_relativa']
rfr.fit(Xm, ym)
fig = px.line(height=600)
fig.add_trace(go.Scatter(y=ym, mode='lines+markers', name='Valores Reais'))
fig.add_trace(go.Scatter(y=rfr.predict(Xm), mode='lines+markers', name='Regressão'))
fig.show()
importancia = pd.Series(rfr.feature_importances_, index=Xm.columns)
importancia.sort_values(ascending=True, inplace=True)
importancia.plot.barh(color='green')
plt.xlabel("Importância")
plt.ylabel("Variável")
Text(0, 0.5, 'Variável')